home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 11 / Mac Magazin and MacEasy Magazine CD - Issue 11.iso / Sharewarebibliothek / Entwickler / WASTE 1.1 C / WEObjects.c < prev    next >
Text File  |  1995-04-29  |  10KB  |  365 lines

  1. // { WASTE PROJECT: }
  2. // { Embedded Objects }
  3.  
  4. // { Copyright © 1993-1995 Marco Piovanelli }
  5. // { All Rights Reserved }
  6.  
  7. #include "WASTEIntf.h"
  8.  
  9. const short kUnknownObjectType = -1;        // { specifies an object type for which no handlers are installed }
  10. const Point kDefaultObjectSize = {32, 32};    // { default object size (32x32 pixels) }
  11.  
  12. // MPW needs topLeft and botRight defined
  13. #ifdef applec
  14. #define topLeft(r)              (((Point *) &(r))[0])
  15. #define botRight(r)             (((Point *) &(r))[1])
  16. #endif
  17.  
  18. typedef struct WEOHTableElement {
  19.     OSType objectType;            // { 4-letter tag identifying object type }
  20.     WENewObjectUPP newHandler;
  21.     WEDisposeObjectUPP freeHandler;
  22.     WEDrawObjectUPP drawHandler;
  23.     WEClickObjectUPP clickHandler;
  24.     UniversalProcPtr cursorHandler;
  25. } WEOHTableElement, *WEOHTablePtr, **WEOHTableHandle;
  26.  
  27. // { static variables }
  28.  
  29. static Handle _weGlobalObjectHandlerTable;
  30.  
  31. pascal OSType WEGetObjectType(WEObjectDescHandle hObjectDesc)
  32. {
  33.     return (*hObjectDesc)->objectType;
  34. } // { WEGetObjectType }
  35.  
  36. pascal Handle WEGetObjectDataHandle(WEObjectDescHandle hObjectDesc)
  37. {
  38.     return (*hObjectDesc)->objectDataHandle;
  39. } // { WEGetObjectDataHandle }
  40.  
  41. pascal Point WEGetObjectSize(WEObjectDescHandle hObjectDesc)
  42. {
  43.     return (*hObjectDesc)->objectSize;
  44. } // { WEGetObjectSize }
  45.  
  46. pascal WEHandle WEGetObjectOwner(WEObjectDescHandle hObjectDesc)
  47. {
  48.     return (*hObjectDesc)->objectOwner;
  49. } // { WEGetObjectOwner }
  50.  
  51. pascal long WEGetObjectRefCon(WEObjectDescHandle hObjectDesc)
  52. {
  53.     return (*hObjectDesc)->objectRefCon;
  54. } // { WEGetObjectRefCon }
  55.  
  56. pascal void WESetObjectRefCon(WEObjectDescHandle hObjectDesc, long refCon)
  57. {
  58.     (*hObjectDesc)->objectRefCon = refCon;
  59. } // { WESetObjectRefCon }
  60.  
  61. pascal short _WELookupObjectType(OSType objectType, Handle hTable)
  62. {
  63.  
  64.     // { look for a WEOHTableElement record for the specified object kind }
  65.     // { in the given object handler table }
  66.  
  67.     short nEntries, index;
  68.  
  69.     // { do nothing if the Object Handler Table has not been inited yet }
  70.     if (hTable == nil) return kUnknownObjectType;
  71.  
  72.     // { calculate entry count }
  73.     nEntries = GetHandleSize(hTable) / sizeof(WEOHTableElement);
  74.  
  75.     // { scan the Object Handler Table looking for a type match }
  76.     for (index = nEntries - 1; index>=0; index--)
  77.     {
  78.         if ((*(WEOHTableHandle)hTable)[index].objectType == objectType) 
  79.             return index;
  80.     }
  81.     
  82.     return kUnknownObjectType;
  83. } // { _WELookupObjectType }
  84.  
  85. pascal OSErr _WEGetIndObjectType(short index, OSType *objectType, WEHandle hWE)
  86. {
  87.     Handle hTable;
  88.     short nEntries;
  89.     OSErr err;
  90.     
  91.     err = weUnknownObjectTypeErr; // { assume failure }
  92.     *objectType = 0L;
  93.  
  94.     // { index must be non-negative }
  95.     if (index < 0) return err;
  96.     
  97.     // { calculate number of entries in the instance-specific handler table }
  98.     nEntries = 0;
  99.     hTable = (*hWE)->hObjectHandlerTable;
  100.     if (hTable != nil)
  101.         nEntries = GetHandleSize(hTable) / sizeof(WEOHTableElement);
  102.  
  103.     // { low indices refer to the instance-specific handler table }
  104.     if (index < nEntries)
  105.     {
  106.         *objectType = (*(WEOHTableHandle)hTable)[index].objectType;
  107.         return noErr;
  108.     }
  109.     // { indices above that refer to the global handler table }
  110.     index = index - nEntries;
  111.  
  112.     // { calculate number of entries in the global handler table }
  113.     nEntries = 0;
  114.     hTable = _weGlobalObjectHandlerTable;
  115.     if (hTable != nil)
  116.         nEntries = GetHandleSize(hTable) / sizeof(WEOHTableElement);
  117.  
  118.     // { return an error code if index is too large }
  119.     if (index >= nEntries)
  120.         return err;
  121.  
  122.     *objectType = (*(WEOHTableHandle)hTable)[index].objectType;
  123.     
  124.     return noErr;
  125. } // { _WEGetIndObjectType }
  126.  
  127. pascal OSErr _WENewObject(OSType objectType, Handle objectDataHandle, WEHandle hWE,
  128.                     WEObjectDescHandle *hObjectDesc)
  129. {
  130.     WEObjectDescPtr pDesc;
  131.     short index;
  132.     OSErr err;
  133.     Handle hTable;
  134.     
  135.     *hObjectDesc = nil;
  136.  
  137.     // { first look up the specified object type in the instance-specific handler table }
  138.     hTable = (*hWE)->hObjectHandlerTable;
  139.     index = _WELookupObjectType(objectType, hTable);
  140.     if (index == kUnknownObjectType)
  141.     {
  142.         // { no match: try with the global handler table }
  143.         hTable = _weGlobalObjectHandlerTable;
  144.         index = _WELookupObjectType(objectType, hTable);
  145.         if (index == kUnknownObjectType)
  146.             hTable = nil;
  147.     }
  148.     
  149.     // { look up the specified object type in the handler table }
  150.     index = _WELookupObjectType(objectType, hTable);
  151.  
  152.     // { create a new relocatable block to hold the object descriptor }
  153.     err = _WEAllocate(sizeof(WEObjectDesc), kAllocClear, (Handle *)hObjectDesc);
  154.     if (err != noErr) return err;
  155.  
  156.     // { lock it down }
  157.     HLock((Handle)*hObjectDesc);
  158.     pDesc = (WEObjectDescPtr)**hObjectDesc;
  159.  
  160.     // { fill in the object descriptor }
  161.     pDesc->objectType = objectType;
  162.     pDesc->objectDataHandle = objectDataHandle;
  163.     pDesc->objectSize = kDefaultObjectSize;
  164.     pDesc->objectTable = hTable;
  165.     pDesc->objectIndex = index;
  166.     pDesc->objectOwner = hWE;
  167.  
  168.     if (hTable != nil) 
  169.     {
  170.         // { call the new handler, if any }
  171.         if ((*(WEOHTableHandle)hTable)[index].newHandler != nil) 
  172.         {
  173.             err = CallWENewObjectProc(&pDesc->objectSize, *hObjectDesc,
  174.                 (*(WEOHTableHandle)hTable)[index].newHandler);
  175.             if (err != noErr) 
  176.             {
  177.                 _WEForgetHandle((Handle *)hObjectDesc);
  178.                 return err;
  179.             }
  180.         }
  181.     }
  182.     
  183.     // { unlock the object descriptor }
  184.     HUnlock((Handle)*hObjectDesc);
  185.  
  186.     // { clear result code }
  187.     return noErr;
  188. } // { _WENewObject }
  189.  
  190. pascal OSErr _WEFreeObject(WEObjectDescHandle hObjectDesc)
  191. {
  192.     WEObjectDescPtr pDesc;
  193.     OSErr retval;
  194.     
  195.     retval = noErr;
  196.  
  197.     // { sanity check: do nothing if we have a null descriptor handle }
  198.     if (hObjectDesc == nil) 
  199.         return nilHandleErr;
  200.  
  201.     // { lock the descriptor record }
  202.     HLock((Handle)hObjectDesc);
  203.     pDesc = *hObjectDesc;
  204.  
  205.     if (pDesc->objectTable != nil) 
  206.     {
  207. #ifdef WASTE_DEBUG
  208.         // { sanity check: make sure object kind matches handler kind }
  209.         _WEAssert(pDesc->objectType == (*(WEOHTableHandle)pDesc->objectTable)
  210.             [pDesc->objectIndex].objectType, "\pObject Type Mismatch");
  211. #endif
  212.  
  213.         // { call the dispose handler, if any }
  214.         if ((*(WEOHTableHandle)pDesc->objectTable)[pDesc->objectIndex].freeHandler != nil) 
  215.         {
  216.             retval = CallWEDisposeObjectProc(hObjectDesc,
  217.                 (*(WEOHTableHandle)pDesc->objectTable)[pDesc->objectIndex].freeHandler);
  218.             pDesc->objectDataHandle = nil;
  219.         }
  220.     }
  221.     
  222.     // { if object kind is unknown or there's no custom dispose handler, use DisposeHandle }
  223.     _WEForgetHandle(&pDesc->objectDataHandle);
  224.  
  225.     // { finally, dispose of the object descriptor itself }
  226.     DisposeHandle((Handle)hObjectDesc);
  227.  
  228.     return retval;
  229. } // { _WEFreeObject }
  230.  
  231. pascal OSErr _WEDrawObject(WEObjectDescHandle hObjectDesc)
  232. {
  233.     WEObjectDescPtr pDesc;
  234.     Rect destRect;
  235.     OSErr retval = noErr;
  236.     PenState state;
  237.     Boolean saveDescLock;
  238.     
  239.     // { lock the object descriptor }
  240.     saveDescLock = _WESetHandleLock((Handle)hObjectDesc, true);
  241.     pDesc = *hObjectDesc;
  242.  
  243.     // { get current pen state }
  244.     // { state.pnLoc has already been set to the bottom left of the rectangle to draw }
  245.     GetPenState(&state);
  246.  
  247.     // { calculate the new pen position }
  248.     state.pnLoc.h = state.pnLoc.h + pDesc->objectSize.h;
  249.  
  250.     // { calculate the destination rectangle }
  251.     *(long *)(&topLeft(destRect)) = DeltaPoint(state.pnLoc, pDesc->objectSize);
  252.     botRight(destRect) = state.pnLoc;
  253.  
  254.     if (pDesc->objectTable != 0) 
  255.     {
  256. #ifdef WASTE_DEBUG
  257.         // { sanity check: make sure object kind matches handler kind }
  258.         _WEAssert(pDesc->objectType == (*(WEOHTableHandle)pDesc->objectTable)[pDesc->objectIndex].objectType,
  259.             "\pObject Type Mismatch");
  260. #endif
  261.  
  262.         // { call the drawing handler, if any }
  263.         if ((*(WEOHTableHandle)pDesc->objectTable)[pDesc->objectIndex].drawHandler != nil) 
  264.             retval = CallWEDrawObjectProc(&destRect, hObjectDesc, 
  265.                         (*(WEOHTableHandle)pDesc->objectTable)[pDesc->objectIndex].drawHandler);
  266.     }
  267.     else
  268.     {
  269.         // { if this object kind was not registered, draw an empty frame }
  270.         PenNormal();
  271.         FrameRect(&destRect);
  272.     }
  273.     
  274.     // { restore original pen state, advancing the pen position by the object width }
  275.     SetPenState(&state);
  276.  
  277.     // { unlock the object descriptor }
  278.     _WESetHandleLock((Handle)hObjectDesc, saveDescLock);
  279.  
  280.     return retval;
  281. } // { _WEDrawObject }
  282.  
  283. pascal Boolean _WEClickObject(Point hitPt, short modifiers, long clickTime,
  284.                                 WEObjectDescHandle hObjectDesc)
  285. {
  286.     WEObjectDescPtr pDesc;
  287.     Boolean saveDescLock;
  288.     Boolean clickHandled = false;
  289.  
  290.     // { lock the object descriptor }
  291.     saveDescLock = _WESetHandleLock((Handle)hObjectDesc, true);
  292.     pDesc = *hObjectDesc;
  293.  
  294.     if (pDesc->objectTable != 0)
  295.     {
  296. #ifdef WASTE_DEBUG
  297.         // { sanity check: make sure object kind matches handler kind }
  298.         _WEAssert(pDesc->objectType = (*(WEOHTableHandle)pDesc->objectTable)[pDesc->objectIndex].objectType,
  299.             "\pObject Type Mismatch");
  300. #endif
  301.  
  302.         // { call the click handler, if any }
  303.         if ((*(WEOHTableHandle)pDesc->objectTable)[pDesc->objectIndex].clickHandler != nil)
  304.             clickHandled = CallWEClickObjectProc(hitPt, modifiers, clickTime, hObjectDesc,
  305.                 (*(WEOHTableHandle)pDesc->objectTable)[pDesc->objectIndex].clickHandler);
  306.     }
  307.  
  308.     // { unlock the object descriptor }
  309.     _WESetHandleLock((Handle)hObjectDesc, saveDescLock);
  310.     
  311.     return clickHandled;
  312. } // { _WEClickObject }
  313.  
  314. pascal OSErr WEInstallObjectHandler(OSType objectType, OSType handlerSelector,
  315.                 UniversalProcPtr handler, WEHandle hWE)
  316. {
  317.     Handle hTable;
  318.     short index;
  319.     WEOHTableElement element;
  320.     OSErr err;
  321.  
  322.     // { if hWE is NIL, install the handler in the global handler table, }
  323.     // { otherwise install the handler in the instance-specific handler table }
  324.     if (hWE == nil)
  325.         hTable = _weGlobalObjectHandlerTable;
  326.     else
  327.         hTable = (*hWE)->hObjectHandlerTable;
  328.  
  329.     // { create the handler table, if it doesn't exist }
  330.     if (hTable == nil) 
  331.     {
  332.         hTable = NewHandle(0);
  333.         err = MemError();
  334.         if (err != noErr) 
  335.             return err;
  336.         if (hWE == nil)
  337.             _weGlobalObjectHandlerTable = hTable;
  338.         else
  339.             (*hWE)->hObjectHandlerTable = hTable;
  340.     }
  341.  
  342.     // { look for the entry corresponding to the specified object type }
  343.     index = _WELookupObjectType(objectType, hTable);
  344.  
  345.     if (index == kUnknownObjectType) 
  346.     {
  347.  
  348.         _WEBlockClr((Ptr)&element, sizeof(element));
  349.         element.objectType = objectType;
  350.         // { previously unknown object type: append a new entry at the end of the handler table }
  351.         index = GetHandleSize(hTable) / sizeof(WEOHTableElement);
  352.         err = _WEInsertSlot(hTable, (Ptr)&element, index, sizeof(element));
  353.         if (err != noErr) 
  354.             return err;
  355.     }
  356.     
  357.     // { install the handler }
  358.     err = _WESetHandler(handlerSelector, (long *)&handler, 
  359.         (void *)&(*(WEOHTableHandle)hTable)[index].objectType);
  360.  
  361.     // { return result code }
  362.     return err;
  363.  
  364. } // { WEInstallObjectHandler }
  365.